package com.myrpc.service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.myrpc.common.Req;
import com.myrpc.common.Res;
import com.myrpc.constant.Constant;
import com.myrpc.handler.RpcDecoder;
import com.myrpc.handler.RpcEncoder;
import com.myrpc.handler.RpcServiceHandler;
import com.myrpc.provider.Rpc;
import com.myrpc.utils.Utils;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * Created with IntelliJ IDEA.
 *
 * @Description:
 * @User: weiyi.liu
 * @Date: 2018-06-08
 * @Time: 12:08
 */
public class ProviderMgr {
	private final static Map<String, Map<Short, Class>> interFaces = new HashMap<String, Map<Short, Class>>();

	/**
	 * 初始化Service端所有提供远程调用的类和方法
	 */
	private static void init() {
		// 扫描所有的带有提供远程接口的类
		Set<Class<?>> classes = Utils.getClasses("com.myrpc.provider.impl");
		for (Class<?> c : classes) {
			Rpc rpc = c.getAnnotation(Rpc.class);
			short version = rpc.version();
			Class clazz = rpc.clazz();
			String simpleName = clazz.getSimpleName();
			Map<Short, Class> impls = interFaces.get(simpleName);
			if (impls == null) {
				impls = new HashMap<Short, Class>();
				interFaces.put(simpleName, impls);
			}
			if (impls.get(version) != null) {
				System.err.println("存在重复的版本");
				return;
			}
			impls.put(version, c);
		}
	}

	/**
	 * 启动一个Service
	 */
	public static void launchService() {
		NioEventLoopGroup boss = new NioEventLoopGroup();
		NioEventLoopGroup worker = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(boss, worker);
		bootstrap.channel(NioServerSocketChannel.class);
		bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
			protected void initChannel(SocketChannel socketChannel) {
				ChannelPipeline pipeline = socketChannel.pipeline();
				pipeline.addLast(new RpcDecoder(Req.class));
				pipeline.addLast(new RpcEncoder(Res.class));
				pipeline.addLast(new RpcServiceHandler());
			}
		});
		bootstrap.option(ChannelOption.SO_BACKLOG, 128);
		bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
		try {
			ChannelFuture future = bootstrap.bind(Constant.SERVICE_PORT).sync();
			System.err.println("服务端启动成功");
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			boss.shutdownGracefully();
			worker.shutdownGracefully();
		}
	}

	/**
	 * 根据客户端的req请求信息反射调用相应的方法
	 * 
	 * @param req
	 * @return
	 */
	public static Object invoke(Req req) {
		Map<Short, Class> impls = interFaces.get(req.getClassName());
		Class impl = impls.get(req.getVersion());
		try {
			Method method = impl.getMethod(req.getMethodName(), req.getParamsTypes());
			return method.invoke(impl.newInstance(), req.getParams());
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			return "";
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			return "";
		} catch (InstantiationException e) {
			e.printStackTrace();
			return "";
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			return "";
		}
	}

	/**
	 * 注册Service进zookeeper
	 */
	public static void regisService() {
		// todo
	}

	public static void main(String[] args) {
		init();
		launchService();
	}
}
